<?php

class News_Application_CommandHandler
{
    var $Log;
    var $Jpg;
    var $Start;
    var $Controller;
    var $Request;
    function News_Application_CommandHandler($controller)
    {
        $this->Controller = $controller;
        $this->Log   = 'data/progress.txt';
        $this->Jpg   = 'data/progress.jpeg';
        $this->Start = time(); 
        $this->Request    = $this->Controller->Settings['request'];
        if (strlen($this->Request) > 0)
        {
            echo $this->Process ();
        }
    }
        
    function GetHandler ()
    {
        $filename = "./messages.xml";
        if (file_exists($filename)) 
        {
		    $xml       = simplexml_load_file($filename);
		    $result    = $xml->xpath("//message[type='{$this->Request}']");
		    $className = $result[0]->class;
		    $className = "{$className}"; 
	        if (class_exists($className))
	        {
	            return new $className($this->Controller); 
	        }  
	        echo "No handler for request type {$this->Request}.\n" .
	             "'{$className}' could not be found.\n";
	        return false;
        }  
        echo "Could not locate {$filename}\n";
        return false;
    } 
        
    function Process ()
    {
        $handler = $this->GetHandler(); 
        if ($handler) 
        {
            return $handler->Signal(); 
        }   
        return false;
    } 
        
    function Display ()
    {
         if (is_array( $_SERVER['argv']))
         {
              $arguments = $_SERVER['argv']; 
              if (sizeof($arguments) > 1)
              {
                  $method = $arguments[1]; 
                  switch ($method)
                  { 
                      case "Notify":
                          $this->Notify ($arguments);
                          exit;
                          break;
                  } 
              }    
         }
    } 
     
    function Notify ($arguments)
    {
        $dir   = "./notify/";
        $array = $this->Open ($dir);
        for ($x=0;$x<sizeof($array);$x++)
        { 
            $this->Request = $array[$x]['type']; // print_r($command);
            $handler       = $this->GetHandler(); 
            if ($handler) 
            {   
                $handler->Invoke($array[$x]);  
                continue;
            }    
            unlink ($array[$x]['path']);
        } 
    } 

    function OpenConnection($groupname)
    {
        $this->Controller->Settings ['group'] = $groupname;
        $this->Controller->Server = new News_Usenet_Server($this->Controller);
        $this->Controller->Imager = new News_UI_Image($this->Controller, false);
        $this->Controller->Imager->Connect();
    }
    
    function LoadIndex($command)
    {    
        $array     = explode ('?', $this->Controller->Read($command['path'])); 
        $groupname = $array[0];// $this->Controller->Read($command['path']); 
        $pageindex = $command['arg1'];
        $pageitem  = $array[1];//$command['arg2'];
        $filename  = "data/{$groupname}.xml"; 
		$this->Controller->LogEntry ("Loading article {$pageitem}", 1, 1, $groupname);
        if (file_exists($filename)) 
        {
		    $xml = simplexml_load_file($filename);
		    $parent  = $xml->xpath("//list/article[@index='{$pageindex}']");
		    $type    = $parent[0]->type;
			$check   = (!isset($type)) || $type=='' || $type=='picture';
		    $result  = $xml->xpath("//list/article[@index='{$pageindex}']/items/article[id='{$pageitem}']"); 
		    $picname = $this->GetArticle ($groupname, $result[0]->id,$check?NULL : "data/temp/{$groupname}", $check);
		    $arr     = explode ('.', $picname);
		    $ext     = array_pop($arr);
//		    echo "{$ext}/{$type}/{$picname}\n\n";
		    $message = "Article loaded {$picname}";
		    if ($ext != 'm4v' && $type != 'm4v' && !$check)
		    {
		        $this->Controller->LogEntry ("Encoding {$picname}", 1, 1, $groupname);
		        $filename = $this->VideoEncode ($picname);
		        $message  = "Conversion failed {$picname}";
		        unlink ($picname);
		        if (file_exists($filename))
		        {
		            $this->CacheName("data/tube/{$groupname}", $result[0]->id, $filename);
		            $picname = $filename;
		            $frame   = $this->VideoFrame ($picname);
		            $message = "Conversion succeeded {$picname}";
		        }
		    }
		    $this->Controller->LogEntry ($message, 1, 1, $groupname);
		    echo "$picname\n"; 
		    return;
        }   
        echo "Could not find group file {$filename}\n";
    }
     
    
    function LoadPage($command)
    {    
        $pageindex = $command['arg1'];
        $groupname = $this->Controller->Read($command['path']); 
        $filename  = "data/{$groupname}.xml";
        if (file_exists($filename)) 
        {
		    $xml = simplexml_load_file($filename);
		    if ($xml)
		    {
                $this->OpenConnection($groupname);
			    $result = $xml->xpath("//list/article");
			        
			    $num = $pageindex * UI_PAGE_SIZE;
			    $min = $num - UI_PAGE_SIZE; 
			    $job = 0;
			    for($x=$min;$x<$num&&$x<sizeof($result);$x++)
			    { 
			        $job ++;
			        $id=$result[$x]->id;
			        $type=$result[$x]->type;
			        echo "Job #{$job}\n------------------------------------\n";
			        if ((!isset($type)) || $type=='' || $type=='picture')
			        {
			            echo $id . "\n"; 
			            $picname = $this->GetArticle ($groupname, $id);
			            echo $picname . "\n"; 
			        }
		            $this->Controller->LogEntry ("Loading page {$pageindex}", $job, UI_PAGE_SIZE, $groupname);
			    }
                $this->Controller->Imager->Disconnect();
		    } 
        }   
    }
    
    function LoadGroup($command)
    {
        $groupname = $this->Controller->Read($command['path']); 
        $startkey  = NULL;
        if (strpos($groupname, '|')!==false)
        {
            $array = explode ('|', $groupname);
            $groupname = $array[0];
            $startkey  = $array[1];
        }
        $filename  = "data/{$groupname}.xml";
		$this->Controller->LogEntry ("Loading group {$groupname}", 1, 1);
        if (file_exists($filename)) 
        {
            return;
        }
        $this->Controller->Settings['group'] = $groupname;
        $this->Controller->Server = new News_Usenet_Server($this->Controller);
        $list = new News_UI_Articlelist($this->Controller, false);
        $list->Load(DOWNLOAD_PACKET_VOLUME, $startkey);
        
        $xml = $list->Display(true);
        $this->Controller->Save ($filename, $xml);   
    }
    
    function Open ($dir)
    {
        $array = array(); 
        if (is_dir($dir)) {
            if ($dh = opendir($dir)) {
                while (($file = readdir($dh)) !== false) {
                    if (!($file=='.'||$file=='..'))
                    {
                        $arr = explode ('.', $file);
                        $ext = array_pop ($arr);
                        $array[] = array('path'=>$dir . $file, 'name'=>$file, 'type'=>$ext, 
                                         'arg1'=>array_pop($arr), 'arg2'=>array_pop($arr)); 
                    }
                }
                closedir($dh);
            }
        }
        return $array;
    }
    
    function VideoEncode ($path)
    { 
        $output = $path . '.m4v';
        echo "Preparing to encode {$path}\n------------------------------\n";
        $command = "ffmpeg -i \"{$path}\" -f mp4 -vcodec libx264 -vpre default " .
                   "-bufsize 1835k -acodec libfaac " .
                   "-b 400k \"{$output}\"";
        echo "Sending {$command}\n------------------------------\n";
        passthru($command);
        return $output;
    }
    
    function VideoFrame($path)
    {
        $output = $path . '.jpeg';
        $c=("ffmpeg -i \"{$path}\" -vcodec mjpeg -vframes 1 -ss 15 -an -f rawvideo -s 320x240 \"{$output}\"");
        passthru($c);
        return $output;
    }
    
    function CacheName ($dir, $id, $name)
    { 
         $arr = explode ('-', $id);
         $key = $arr[0];
         $this->Controller->Imager->Save ("{$dir}/{$key}.name", $name);   
    }

    function GetArticle ($group, $id, $dir = NULL, $checkit = true)
    { 
        $b64 = base64_encode ($id);
        $filename = $dir ? "{$dir}/{$b64}" : "data/temp/{$group}/{$b64}"; 
        
        if (file_exists($filename) && !$dir)
        {
            return $filename;
        }
        if (!$checkit)
        {
                $dir = "data/tube/{$group}";
                $arr = explode ('-', $id);
                $key = $arr[0];
                $chk = "{$dir}/{$key}.name";
                if (file_exists($chk))
                {
                    return $this->Controller->Read ($chk);  
                }
        }
        
        $this->Controller->Settings ['group'] = $group;
        $this->Controller->Settings ['id']    = $id;
        
        // create server and downloader instances 
        if (!$this->Controller->Imager)
        {
            $this->Controller->Server = new News_Usenet_Server($this->Controller);
            $this->Controller->Imager = new News_UI_Image($this->Controller);
        }
        #echo "Article id #{$id}\n";
        
        $articles = $this->Controller->Imager->DownloadArticles($id, !$checkit);  
//         ob_start();
//         var_dump ($articles);
//         $raw = ob_get_contents();
//         ob_end_clean();
  
        $content  = $this->Controller->Imager->Assemble ($articles);
        
        
        $body  = array();        
        for ($x=0;$x < sizeof($content); $x++)
        {
		    $body[] = trim($content[$x]['body']);  
        } 
        
        if ($dir || !$checkit)
        {
            $full = $body[0];//implode ('', $body);
        
			$fname      = $b64;    
            if (preg_match("/^=ybegin.*name=([^\\r\\n]+)/im", $full, $header))                      
            {                 
				$fname = trim(utf8_encode($header[1]));                  
            }                      
            else if (preg_match ('/begin\s+(\d+)\s+(.*)/im', $full, $header))
            {	    
				$fname = trim(utf8_encode($header[2]));                          
            }    
            $filename = "{$dir}/{$fname}";
            if (!$checkit)
            {   
                $fname = str_replace(' ', '--', $fname);
                $dir = "data/tube/{$group}";
                if (!is_dir($dir)) mkdir ($dir);
                $filename = "{$dir}/{$fname}";
                $this->CacheName($dir, $id, $filename);  
            }
        }
        
        if ($this->Controller->Imager->Yenc)
        {  
	        $enc  = new yenc($checkit ? NULL : $this->Controller);                                                                                                                                                                         
	        $data = $enc->decode($body);   
	        $this->Controller->Imager->Save ($filename, $data);  
	        echo filesize ($filename) . " bytes saved\n";
	        return $filename;
        }
        
		
		$encoding = $content[0]['header']['content-transfer-encoding'];
		if (strlen($encoding) == 0) $encoding = 'uuencode';
		
		
        $array = array ('header' => array('content-transfer-encoding' => $encoding), 
                        'body'   => implode("\n", $body));  
      

        $body = $array['body'];
		if (preg_match("/^begin\s+\d{3}\s+(.*)$/im", $body, $header))
		{
            $body = str_replace($header[0], "", $body);   
            $array['body'] = trim($body);
		}     
		
		
        $data = decode_message_content($array);
	    $this->Controller->Imager->Save ($filename, $data);  
        
	    
	    echo filesize ($filename) . " bytes saved\n";
	    
	    
	    if (!$checkit) return $filename;
	    
	    #echo "Testing image...\n";
	    $im = @imagecreatefromjpeg ($filename);
	    if (!$im) $im = @imagecreatefromgif($filename); 
	    if ($im)
	    {
	        imagedestroy($im);
            return $filename;
	    } 
	    
	    echo "Imaging test failed!! Deleting...\n";
	    unlink ($filename);
//	    $this->Controller->Imager->Save ("error".time().".txt", $raw);  
	    return "{$filename} deleted.\n";
        #echo $this->Controller->Imager->Yenc;
        
    }
}